#pragma once 
#include <cassert>
#include <iostream>
#include <mutex>
using std::endl;
using std::cout;

//条件编译，对linux和window分开处理
#ifdef _WIN64 
	typedef unsigned long long PAGE_ID;
#elif _WIN32
	typedef size_t PAGE_ID;
#elif __LP64__
    typedef unsigned long long PAGE_ID;
#elif defined(__ILP32__)
    typedef size_t PAGE_ID;
#endif

static void*& NextSite(void* obj)
{
    return *(void**)obj;
}

class FreeList
{
public:
    void push(void* obj)
    {
        NextSite(obj) = _freelist;
        _freelist = obj;
    }

    void* pop()
    {
        assert(_freelist);
        void* ret = _freelist;
        _freelist = NextSite(_freelist);
        return ret;
    }

    bool empty()
    {
        return _freelist == nullptr;
    }
private:
    void* _freelist = nullptr;
};


 
class Size
{
public:
    static size_t _RoundUp(size_t size, size_t alignNum)
    {
        if(size % alignNum == 0)
        {
            return size;
        }
        else
        {
            return (size / alignNum + 1) * alignNum;
        }
    }

    //向上取整，给五个范围分配不同的对齐数，使得内存损失大约都在10%
    static size_t RoundUp(size_t size)
    {
    // 整体控制在最多10%左右的内碎片浪费 
	// [1,128]					8byte对齐	 freelist[0,16) 
	// [128+1,1024]				16byte对齐	 freelist[16,72) 
	// [1024+1,8*1024]			128byte对齐	 freelist[72,128) 
	// [8*1024+1,64*1024]		1024byte对齐 freelist[128,184) 
	// [64*1024+1,256*1024]		8*1024byte对齐 freelist[184,208)
        if(size <= 128)
        {
            return _RoundUp(size, 8);
        }
        else if(size <= 1024)
        {
            return _RoundUp(size, 16);
        }
        else if(size <= 8 * 1024)
        {
            return _RoundUp(size, 128);
        }
        else if(size <= 64 * 1024)
        {
            return _RoundUp(size, 1024);
        }
        else if(size <= 256 * 1024)
        {
            return _RoundUp(size, 8 * 1024);
        }
        else
        {
            assert(false);
            return -1;
        }
    }

    static size_t _index(size_t size, size_t alignNum)
    {
        if(size % alignNum == 0)
        {
            return size % alignNum - 1;
        }
        else
        {
            return size % alignNum;
        }
    }

    static size_t index(size_t size)
    {
    // 整体控制在最多10%左右的内碎片浪费 
	// [1,128]					8byte对齐	 freelist[0,16) 
	// [128+1,1024]				16byte对齐	 freelist[16,72) 
	// [1024+1,8*1024]			128byte对齐	 freelist[72,128) 
	// [8*1024+1,64*1024]		1024byte对齐 freelist[128,184) 
	// [64*1024+1,256*1024]		8*1024byte对齐 freelist[184,208)
        int count_arr[4] = {16, 56, 56, 56};
        if(size <= 128)
        {
            return _index(size, 8);
        }
        else if(size <= 1024)
        {
            return _index(size, 16) + count_arr[0];
        }
        else if(size <= 8 * 1024)
        {
            return _index(size, 128) + count_arr[0] + count_arr[1];
        }
        else if(size <= 64 * 1024)
        {
            return _index(size, 1024) + count_arr[0] + count_arr[1] + count_arr[2];
        }
        else if(size <= 256 * 1024)
        {
            return _index(size, 8 * 1024) + count_arr[0] + count_arr[1] + count_arr[2]
            + count_arr[3];
        }
        else
        {
            assert(false);
            return -1;
        }
    }

    class Span
    {
    public:
        size_t _curPage;               //当前页
        size_t _pageCount;             //页的数量

        Span* _next = nullptr;         //双向循环链表指针
        Span* _prev = nullptr;

        size_t _allocNum = 0;          //分配给threadCache的内存数量
        FreeList* _freeList = nullptr; //当前span剩余的以及回收的自由链表节点
    };

    class SpanList
    {
    public:
        SpanList()
        {
            _head = new Span;
            _head->_next = _head;
            _head->_prev = _head;
        }

        void insert(Span* pos, Span* in)
        {
            assert(pos);
            Span* prev = pos->_prev;
            prev->_next = in;
            in->_prev = prev;

            in->_next = pos;
            pos->_prev = in;
        }

        void erase(Span* pos) //对于删除的结点，未在当前的函数处理
        {
            assert(pos);
            assert(pos != _head);

            Span* prev = pos->_prev;
            Span* next = pos->_next;

            prev->_next = next;
            next->_prev = prev;
        }
    private:
        Span *_head;      //带头双向循环链表
    public:
        std::mutex _lock; // 桶锁，初始化？
    };
};